﻿
using JavaCodeGeneratorConsole.entity;
using JavaCodeGeneratorConsole.utils;
using Newtonsoft.Json;
using System.Dynamic;
using System.Reflection;
using static System.Net.Mime.MediaTypeNames;

namespace JavaCodeGeneratorConsole
{
    public class Program
    {
        public static void Main()
        {
            // 初始化
            AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;


            Console.WriteLine("欢迎使用 Sqlite 3 Java 代码生成器");
            Console.WriteLine("提示：数据库必须建表");
            Console.Write("请输入数据库绝对路径：");
            string? dbPath = Console.ReadLine();
            List<TableInfo> tableInfos = null;
            try
            {
                tableInfos = DbUtils.GetTableInfos(dbPath);
            }
            catch (Exception e)
            {
                Console.WriteLine("未找到数据库文件，请重新运行程序，按任意键关闭！");
                Console.ReadLine();
                return;
            }
            Console.Write("请输入包名(回车后生成)：");
            string? packageName = Console.ReadLine();

            // 创建文件夹
            if (Directory.Exists("./generator"))
            {
                Directory.Delete("./generator", true);
            }
            Directory.CreateDirectory("./generator/entity/");
            Directory.CreateDirectory("./generator/mapper/");
            Directory.CreateDirectory("./generator/service/");
            Directory.CreateDirectory("./generator/service/impl/");
            Directory.CreateDirectory("./generator/controller/");

            // 遍历列表，将所有的文件输到对应的文件夹
            for (int i = 0; i < tableInfos.Count; i++)
            {
                tableInfos[i].packageName = packageName;
                Dictionary<string, object> dictionary = GetData(tableInfos[i]);
                OutEntity(dictionary);
                OutMapper(dictionary);
                OutService(dictionary);
                OutServiceImpl(dictionary);
                OutController(dictionary);
            }

            // 提示
            Console.WriteLine(">>>>> 成功在本目录生成，按任意键关闭 <<<<<");
            Console.ReadLine();

        }

        private static Dictionary<string, object> GetData(TableInfo tableInfo)
        {
            tableInfo.Update();
            //Console.WriteLine(tableInfo.servicePackageName);

            List<TableColunm> tableDatas = tableInfo.tableDatas;
            Dictionary<string, object>[] tableColunms = new Dictionary<string, object>[tableDatas.Count];

            for (int i = 0; i < tableDatas.Count; i++)
            {
                TableColunm item = tableDatas[i];
                item.Update();

                string itemJson = JsonConvert.SerializeObject(item);
                Dictionary<string, object> obj = JsonConvert.DeserializeObject<Dictionary<string, object>>(itemJson);
                tableColunms[i] = (obj);
            }
            //E:\data\GITEE\java-music-player\db\jmusic-player.db
            string json = JsonConvert.SerializeObject(tableInfo);
            Dictionary<string, object> tableInfoDec = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
            tableInfoDec.Remove("tableDatas");
            tableInfoDec.Add("tableDatas", tableColunms);
            return tableInfoDec;
        }

        public static void OutEntity(Dictionary<string, object> tableInfoDec)
        {
            string content = GetFileContent("entity");
            dynamic template = Mustachio.Parser.Parse(content);
            var result = template(tableInfoDec);
            string filePath = $"./generator/entity/{tableInfoDec["entityName"]}.java";
            File.WriteAllText(@filePath, result);
        }
        public static void OutMapper(Dictionary<string, object> tableInfoDec)
        {
            string content = GetFileContent("mapper");
            dynamic template = Mustachio.Parser.Parse(content);
            var result = template(tableInfoDec);
            string filePath = $"./generator/mapper/{tableInfoDec["mapperName"]}.java";
            File.WriteAllText(@filePath, result);
        }
        public static void OutService(Dictionary<string, object> tableInfoDec)
        {
            string content = GetFileContent("service");
            dynamic template = Mustachio.Parser.Parse(content);
            var result = template(tableInfoDec);
            string filePath = $"./generator/service/{tableInfoDec["serviceName"]}.java";
            File.WriteAllText(@filePath, result);
        }
        public static void OutServiceImpl(Dictionary<string, object> tableInfoDec)
        {
            string content = GetFileContent("serviceImpl");
            dynamic template = Mustachio.Parser.Parse(content);
            var result = template(tableInfoDec);
            string filePath = $"./generator/service/impl/{tableInfoDec["serviceImplName"]}.java";
            File.WriteAllText(@filePath, result);
        }
        public static void OutController(Dictionary<string, object> tableInfoDec)
        {
            string content = GetFileContent("controller");
            dynamic template = Mustachio.Parser.Parse(content);
            var result = template(tableInfoDec);
            string filePath = $"./generator/controller/{tableInfoDec["controllerName"]}.java";
            File.WriteAllText(@filePath, result);
        }

        public static string GetFileContent(string fileName)
        {
            //获得正在运行类所在的名称空间
            Type type = MethodBase.GetCurrentMethod().DeclaringType;
            string _namespace = type.Namespace;
            //获得当前运行的Assembly
            Assembly _assembly = Assembly.GetExecutingAssembly();
            string resourceName = $"{_namespace}.templates.{fileName}.template";
            Stream stream = _assembly.GetManifestResourceStream(resourceName);
            stream.Position = 0;
            StreamReader reader = new StreamReader(stream);
            string text = reader.ReadToEnd();
            reader.Close();
            stream.Close();
            return text;
        }

        // DLL配置
        private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs e)
        {
            //项目的命名空间为myapp, 嵌入dll资源在libs文件夹下，所以这里用的命名空间为： myapp.libs.
            //获得正在运行类所在的名称空间
            Type type = MethodBase.GetCurrentMethod().DeclaringType;
            string _namespace = type.Namespace;
            string _resName = $"{_namespace}.libs.{new AssemblyName(e.Name).Name}.dll";
            using (var _stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(_resName))
            {
                byte[] _data = new byte[_stream.Length];
                _stream.Read(_data, 0, _data.Length);
                return Assembly.Load(_data);
            }
        }
    }
}